﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Globalization;

namespace Excell_On_Services.Models
{
    public class EFEOSRepository : IEOSRepository
    {

        private ExcellOnServiceEntities db = new ExcellOnServiceEntities();
        public ExcellOnServiceEntities DB
        {
            get { return db; }
            set { db = value; }
        }

        public Guid GetIdByUsername(string username)
        {
            var user = DB.aspnet_Users.First(u => u.UserName == username);
            return user.UserId;
        }


        #region Employee

        public IQueryable<Employee> FindAllEmployees()
        {
            return DB.Employees;
        }

        public IQueryable<Employee> FindEmployeesByName(string name)
        {
            return DB.Employees.Where(e => e.FullName == name);
        }

        public Employee FindEmployeesById(Guid employeeID)
        {
            if (DB.Employees.Count() > 0)
                return DB.Employees.FirstOrDefault(p => p.EmployeeID == employeeID);
            else
                return null;
        }



        public void AddEmployee(Employee employee)
        {
            DB.AddToEmployees(employee);
        }

        public void UpdateEmployee(Employee employee)
        {
            var existingEmployee = DB.GetById<Employee>(employee.EmployeeID, "EmployeeID");
            existingEmployee.FullName = employee.FullName;
            //existingEmployee.Email = employee.Email;
            existingEmployee.Address = employee.Address;
            existingEmployee.BirthDate = employee.BirthDate;
            existingEmployee.Sex = employee.Sex;
            existingEmployee.Phone = employee.Phone;
            existingEmployee.Notes = employee.Notes;
            existingEmployee.isLock = employee.isLock;
        }

        public bool DeleteEmployee(Guid employeeID)
        {
            var employee = DB.GetById<Employee>(employeeID,"EmployeeID");
            DB.DeleteObject(employee);
            return true;
        }

        public IQueryable<Employee> FindEmployeesInPage(int pageNumber, int pageSize)
        {
            return DB.Employees.OrderBy(e => e.FullName).Skip(pageSize * pageNumber).Take(pageSize);
        }

        public int GetEmployeesCount()
        {
            return DB.Employees.Count();
        }

        #endregion

        #region Department.
        public IQueryable<Department> FindAllDepartments()
        {
            return DB.Departments;
        }

        public IQueryable<Department> FindDepartmentByName(string name)
        {
            return DB.Departments.Where(d => d.DepartmentName == name);
        }

        public void AddDepartment(Department department)
        {
            DB.AddToDepartments(department);
        }

        public void UpdateDepartment(Department department)
        {
            var existingDepartment = DB.GetById<Department>(department.DepartmentID,"DepartmentID");
            existingDepartment.DepartmentName = department.DepartmentName;
            existingDepartment.Description = department.Description;
        }

        public bool DeleteDepartment(int DepartmentID)
        {
            //var existingDepartment = DB.GetById<Department>(DepartmentID, "DepartmentID");
            var existingDepartment = FindDeparmentById(DepartmentID);
            if (existingDepartment == null)
                return false;
            if (existingDepartment.Employees.Count() > 0)
            {
                return false;
            }
            else
            {
                DB.DeleteObject(existingDepartment);
                return true;
            }
        }

        public IQueryable<Department> FindDepartmentsInPage(int pageNumber, int pageSize)
        {
            return
                //DB.Departments.Include("Tags").Include("User")
                DB.Departments.OrderBy(d=>d.DepartmentID).Skip(pageSize * pageNumber).Take(pageSize);
        }

        public int GetDepartmentsCount()
        {
            return DB.Departments.Count();
        }

        public Department FindDeparmentById(int departmentId)
        {
            return DB.Departments.First(d => d.DepartmentID == departmentId);
        }

        #endregion
        
        #region Client

        public void AddClient(Client client)
        {
            DB.AddToClients(client);
        }

        public void UpdateClient(Client client)
        {
            var item = DB.Clients.Where(c=>c.isStatus == false).First(c => c.ClientID == client.ClientID);
            if (item == null)
                return;
            item.Address = client.Address;
            item.CompanyName = client.CompanyName;
            //item.Email = client.Email;
            item.Phone = client.Phone;
            item.Description = client.Description;
            item.Product_Description = client.Product_Description;

        }


        public IQueryable<Client> FindClientsInPage(int pageNumber, int pageSize)
        {
            return DB.Clients.Where(c=>c.isStatus == false).OrderBy(c => c.ClientID).Skip(pageSize * pageNumber).Take(pageSize);
        }

        public IQueryable<Client> FindClientsByName(string name)
        {
            return DB.Clients.Where(c => c.CompanyName == name && c.isStatus == false);
        }

        public Client FindClientsByID(Guid ID)
        {
            return DB.Clients.Where(c => c.isStatus == false).First(c => c.ClientID == ID);
        }

        public Client FindClientByUsername(string username)
        {
            if(GetClientCount() >0 )
                return DB.Clients.Where(c => c.isStatus == false).First(c =>c.aspnet_Users.UserName == username);
            return null;
        }

        public int GetClientCount()
        {
            return DB.Clients.Where(c=>c.isStatus == false).Count();
        }

        public bool DeleteClient(Guid clientID)
        {
            var existingClient = FindClientsByID(clientID);
            if (existingClient == null)
                return false;
            existingClient.isStatus = true;
            CommitChanges();
            return true;
        }

        public IQueryable<Client> SearchClient(string type, string search,int pageNumber, int pageSize)
        {
            switch (type)
            {
                case "1": // theo Company name
                    return
                    DB.Clients.Where(c => c.CompanyName.Contains(search)).OrderBy(c => c.ClientID).Skip(pageSize * pageNumber).Take(pageSize);
                case "2":// client ID
                    break;
                case "3":// phone
                    return DB.Clients.Where(c => c.Phone.Contains(search)).OrderBy(c => c.ClientID).Skip(pageSize * pageNumber).Take(pageSize);
                case "4": //Email
                    //return DB.Clients.Where(.Contains(search)).OrderBy(c => c.ClientID).Skip(pageSize * pageNumber).Take(pageSize);
                    break;
            }
            return null;
        }


        

        #endregion

        #region Service
        public void UpdateService(Service service)
        {
            var item = DB.Services.First(s => s.ServiceID == service.ServiceID);
            if (item == null)
            {
                throw new Exception("can not find this service in database");
            }
            else
            {
                item.ParentID = service.ParentID;
                item.Name = service.Name;
                item.Price = service.Price;
                item.Description = service.Description;
            }
        }

        public void DeleteService(int id)
        {
            throw new NotImplementedException();
        }

        public void AddService(Service service)
        {
            DB.AddToServices(service);
        }

        public void AddServiceHaveParent(Service service, int id)
        {
            throw new NotImplementedException();
        }

        public Service FindServiceById(int id)
        {
            return DB.Services.First(s => s.ServiceID == id);
        }

        public int GetServiceCount()
        {
            return DB.Services.Count();
        }

        public IQueryable<Service> GetServicesByParent(int id)
        {
            return DB.Services.Where(s => s.ParentID == id);
        }

        public IQueryable<Service> FindServicesInPage(int pageNumber, int pageSize)
        {
            return DB.Services.OrderBy(s=>s.ServiceID).Skip(pageSize * pageNumber).Take(pageSize);
        }

        public IQueryable<Service> FindAllServicesExpertID(int id)
        {
            return DB.Services.Where(s=>s.ServiceID !=id);
        }

        public IQueryable<Service> FindAllServices()
        {
            return DB.Services;
        }

        #endregion

        #region Order

        public int GetOrdersCount()
        {
            return DB.OrderServices.Count();
        }

        public int GetOrdersByClientCount(string username)
        {
            return DB.OrderServices.Where(o => o.Client.aspnet_Users.UserName == username).Count();
        }

        public void AddOrderByClient(Cart cart, Guid ClientID)
        {
            OrderService order = new OrderService();
            order.ClientID = ClientID;
            order.OrderDate = DateTime.Now;
            order.Status = false;
            foreach(var item in cart.Lines)
            {
                var orderDetail = new OrderDetail
                {
                    OrderID = order.OrderID,
                    ServiceID = item.Service.ServiceID,
                    Price = item.Service.Price,
                    StartDate = item.StartDate,
                    EndDate = item.EndDate,
                    Quantity = item.Quantity
                    
                };
                order.OrderDetails.Add(orderDetail);
            }
            DateTime mindate =(DateTime) order.OrderDetails.Min(d => d.StartDate);
            DateTime maxDate = (DateTime)order.OrderDetails.Max(d => d.EndDate);

            long days = (long)((TimeSpan)(maxDate - mindate)).TotalDays;
            long count = days / 30;
            if (count == 0)
                count = 1;
            decimal totalMonmey = cart.ComputeTotalValue();
            for (int i = 0; i < count; i++)
            {
                OrderPayment payment = new OrderPayment();
                payment.DurationDate = mindate.AddDays(i*30);
                payment.OrderID = order.OrderID;
                payment.Payment = totalMonmey / count;
                if (i == count - 1)
                    payment.Payment = totalMonmey/count + totalMonmey%count;
                order.OrderPayments.Add(payment);
            }
                
            DB.AddToOrderServices(order);
            CommitChanges();
        }

        public OrderPayment getPaymentById(int paymentID)
        {
            return DB.OrderPayments.First(p => p.PaymentID == paymentID);
        }

        public void AddOrder(OrderService order)
        {
            throw new NotImplementedException();
        }

        public void UpdateOrder(OrderService order)
        {
            var existingOrder = FindOrderById(order.OrderID);
            existingOrder.Status = order.Status;
            existingOrder.OrderDate = order.OrderDate;

        }

        public void DeleteOrder(int id)
        {
            throw new NotImplementedException();
        }

        public OrderService FindOrderById(int id)
        {
            return DB.OrderServices.First(o => o.OrderID == id);
        }

        public OrderService FindOrderClientById(int id,string username)
        {
            return DB.OrderServices.First(o => o.Client.aspnet_Users.UserName == username && o.OrderID == id);
        }

        public IQueryable<OrderService> FindOrdersInPage(int pageNumber, int pageSize)
        {
            return DB.OrderServices.OrderByDescending(d => d.OrderID).Skip(pageSize * pageNumber).Take(pageSize);
        }

        public IQueryable<OrderService> SearchOrdersInPage(int pageNumber, int pageSize, int type,string strSearch)
        {
            switch(type)
            {
                case 1: // by client Name
                    return DB.OrderServices.Where(o => o.Client.CompanyName == strSearch).OrderByDescending(d => d.OrderID).Skip(pageSize * pageNumber).Take(pageSize);
                case 2: // by status
                    bool check = Convert.ToBoolean(strSearch);
                    return DB.OrderServices.Where(o => o.Status == check).OrderByDescending(d => d.OrderID).Skip(pageSize * pageNumber).Take(pageSize);
                case 3: // by Date Order
                    DateTime date = DateTime.ParseExact(strSearch, "MM/dd/yyyy",CultureInfo.InvariantCulture);
                    return DB.OrderServices.Where(o => ((DateTime)o.OrderDate).Date == date).OrderByDescending(d => d.OrderID).Skip(pageSize * pageNumber).Take(pageSize);
            }
            return null;
            
                
        }

        public IQueryable<OrderService> FindOrdersByClient(string username,int pageNumber, int pageSize)
        {
            return DB.OrderServices.Where(o => o.Client.aspnet_Users.UserName == username).OrderByDescending(d => d.OrderID).Skip(pageSize * pageNumber).Take(pageSize);
        }

        public IQueryable<OrderDetail> FindOrderDetailsByOrderId(int orderId)
        {
            return DB.OrderDetails.Where(o => o.OrderID == orderId);
        }
            
        #endregion

        #region About
        public int GetAboutCount()
        {
            return DB.Abouts.Count();
        }

        public void AddAbout(About about)
        {
            DB.AddToAbouts(about);
        }

        public void UpdateAbout(About about)
        {
            var a = FindAboutById(about.AboutID);
            a.Content = about.Content;
            a.PublishedDate = about.PublishedDate;
            a.ModifiedDate = about.ModifiedDate;
            a.Title = about.Title;
            CommitChanges();
        }

        public About FindAboutById(int id)
        {
            return DB.Abouts.First( a =>a.AboutID == id);
        }

        public IQueryable<About> FindAboutInPage(int pageNumber, int pageSize)
        {
            return DB.Abouts.OrderBy(a => a.AboutID).Skip(pageSize * pageNumber).Take(pageSize);
        }

        public IQueryable<CategoryNew> FindAllCategory()
        {
            return DB.CategoryNews;
        }
         

        #endregion

        public void CommitChanges()
        {
            DB.SaveChanges();
        }


        
    }
}